package com.xxd.rpt3.service.impl;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import com.xxd.rpt3.Entity.Department;
import com.xxd.rpt3.Entity.JwtTokenHis;
import com.xxd.rpt3.Entity.User;
import com.xxd.rpt3.repository.JwtTokenHisRepository;
import com.xxd.rpt3.repository.UserRepository;
import com.xxd.rpt3.service.UserService;
import com.xxd.utils.EHCacheUtils;
import com.xxd.utils.JwtUtil;
import com.xxd.utils.PasswordUtil;

@Service
public class UserImpl implements UserService {
	@Autowired
	UserRepository userRepository;
	@Autowired
	JwtTokenHisRepository jwtTokenHisRepository;

	@Override
	public User getUserById(int id) {
		return userRepository.getOne(id);
	}

	@Override
	public Page<User> findByPage(final User user, int page, int pageSize) {
		Pageable pageable = PageRequest.of(page - 1, pageSize);
		Specification<User> spec = new Specification<User>() {
			@Override
			public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
				List<Predicate> predicates = new ArrayList<>();
				Path<String> name = root.get("name");
				Path<Department> depart = root.get("department");
				if (user.getName() != null) {
					Predicate predicate = criteriaBuilder.like(name, "%${user.getName()}%");
					predicates.add(predicate);
				}
				if (user.getDepartment() != null) {
					Predicate predicate = criteriaBuilder.equal(depart, user.getDepartment());
					predicates.add(predicate);
				}
				Predicate[] a = new Predicate[predicates.size()];
				return criteriaBuilder.and(predicates.toArray(a));
			}
		};
		return userRepository.findAll(spec, pageable);
	}

	@Override
	public User findByName(String instr) {
		return userRepository.findUserByCode(instr);
	}

	@Override
	public User saveUser(User user) {
		user.setSalt(PasswordUtil.createSalt());
		user.setPassword(PasswordUtil.encryption(user.getPassword(), user.getSalt()));
		return userRepository.save(user);
	}

	@Override
	public String signToken(User user) {
		JwtUtil jwtUtil = new JwtUtil(user);
		//如果数据库中token没有，则插入，否则刷新token
		JwtTokenHis jwtTokenHis =  jwtTokenHisRepository.findJwtTokenHisByUserCode(user.getCode());
		if(jwtTokenHis == null){
			jwtTokenHis = new JwtTokenHis();
			jwtTokenHis.setUserCode(user.getCode());
		}
		jwtTokenHis.setKey(jwtUtil.getTokenId());
		jwtTokenHis.setValue(jwtUtil.getToken());
		jwtTokenHis.setSalt(user.getSalt());
		jwtTokenHisRepository.save(jwtTokenHis);

		// 重新签发token
		// 1.先获取缓存token
		Object userKey = EHCacheUtils.getTokenCache(user.getCode());
		// 2.如果无，则新增缓存，如果没有，则刷新缓存
		if (userKey == null) {
			EHCacheUtils.setTokenCache(user.getCode(), jwtUtil.getTokenId());
			EHCacheUtils.setTokenCache(jwtUtil.getTokenId(), jwtTokenHis);
		} else {// 3.如果有，则删除之前缓存，再更新当前缓存
			EHCacheUtils.delTokenCache(userKey);
			EHCacheUtils.setTokenCache(user.getCode(), jwtUtil.getTokenId());
			EHCacheUtils.setTokenCache(jwtUtil.getTokenId(), jwtTokenHis);
		}
		return jwtUtil.getTokenId();
	}


	@Override
	public String signToken(User user, int keepDay) {
		JwtUtil jwtUtil = new JwtUtil(user,keepDay);
		//如果数据库中token没有，则插入，否则刷新token
		JwtTokenHis jwtTokenHis =  jwtTokenHisRepository.findJwtTokenHisByUserCode(user.getCode());
		if(jwtTokenHis == null){
			jwtTokenHis = new JwtTokenHis();
			jwtTokenHis.setUserCode(user.getCode());
		}
		jwtTokenHis.setKey(jwtUtil.getTokenId());
		jwtTokenHis.setValue(jwtUtil.getToken());
		jwtTokenHis.setSalt(user.getSalt());
		jwtTokenHis.setKeepDay(keepDay);
		jwtTokenHisRepository.save(jwtTokenHis);

		// 重新签发token
		// 1.先获取缓存token
		Object userKey = EHCacheUtils.getTokenCache(user.getCode());
		// 2.如果无，则新增缓存，如果没有，则刷新缓存
		if (userKey == null) {
			EHCacheUtils.setTokenCache(user.getCode(), jwtUtil.getTokenId());
			EHCacheUtils.setTokenCache(jwtUtil.getTokenId(), jwtTokenHis);
		} else {// 3.如果有，则删除之前缓存，再更新当前缓存
			EHCacheUtils.delTokenCache(userKey);
			EHCacheUtils.setTokenCache(user.getCode(), jwtUtil.getTokenId());
			EHCacheUtils.setTokenCache(jwtUtil.getTokenId(), jwtTokenHis);
		}
		return jwtUtil.getTokenId();
	}

	@Override
	public void logout(String token){
		new Thread(new Runnable() {
			@Override
			public void run() {
				try{
					JwtTokenHis jwtTokenHis =  jwtTokenHisRepository.findJwtTokenHisByKey(token);
					if(jwtTokenHis !=null){
						jwtTokenHisRepository.delete(jwtTokenHis);
						EHCacheUtils.delTokenCache(jwtTokenHis.getUserCode());
						EHCacheUtils.delTokenCache(jwtTokenHis.getKey());
					}
					Object cache = EHCacheUtils.getTokenCache(token);
					if(cache !=null){
						jwtTokenHis = (JwtTokenHis)cache;
						jwtTokenHisRepository.delete(jwtTokenHis);
						EHCacheUtils.delTokenCache(jwtTokenHis.getUserCode());
						EHCacheUtils.delTokenCache(jwtTokenHis.getKey());
					}
				}catch(Exception e){
					e.printStackTrace();
				}
			}
		}).start();
	}
}
